package com.yanqu.road.entity.buildDaoUtil;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.yanqu.road.entity.FieldTypeAnnotation;
import com.yanqu.road.entity.activity.pawnshop.*;
import com.yanqu.road.entity.activity.yuanbaolottery.YuanBaoLotteryConfig;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.string.StringUtils;

public class BuildConfigActivitySql {

    public static void main(String[] args) {
        Class<YuanBaoLotteryConfig> clz = YuanBaoLotteryConfig.class;
        String tableName = "";
        String className = clz.getSimpleName();
        Field[] fields = clz.getDeclaredFields();
        List<String> orderASCList = new ArrayList<>();
        List<String> orderDESCList = new ArrayList<>();
        List<String> selectList = new ArrayList<>();
        
        // 打印SQL=======================================================================
        if (clz.isAnnotationPresent(FieldTypeAnnotation.class)) {
            tableName = "`" + clz.getAnnotation(FieldTypeAnnotation.class).tableName() + "`";
        
	        List<String> keyList = new ArrayList<>();
	        List<String> keyList1 = new ArrayList<>();
	        String fildStr = "";
	        for (Field field : fields) {
	            if (field.isAnnotationPresent(FieldTypeAnnotation.class)) {
	                FieldTypeAnnotation fieldTypeAnnotation = field.getAnnotation(FieldTypeAnnotation.class);
	                String fieldName = "`" + field.getName() + "`";
	                String fieldDesc = "'" + fieldTypeAnnotation.desc() + "'";
	                if (fieldTypeAnnotation.orderASC()) {
	                	orderASCList.add(fieldName);
	                }
	                if (fieldTypeAnnotation.orderDESC()) {
	                	orderDESCList.add(fieldName);
	                }
	                if (fieldTypeAnnotation.select()) {
	                    selectList.add(fieldName);
	                }
	                if (fieldTypeAnnotation.update()) {
	                    keyList.add(fieldName);
	                    keyList1.add(fieldName);
	                }
	                if (field.getType() == int.class || field.getType() == boolean.class) {
	                    fildStr += "  " + fieldName + " int(11) NOT NULL COMMENT " + fieldDesc + ",\n";
	                } else if (field.getType() == long.class) {
	                    fildStr += "  " + fieldName + " bigint(20) NOT NULL COMMENT " + fieldDesc + ",\n";
	                } else if (field.getType() == String.class || field.getType() == List.class || 
	                		field.getType() == BigInteger.class || field.getType() == BigDecimal.class) {
	                    fildStr += "  " + fieldName + " varchar(255) NOT NULL COMMENT " + fieldDesc + ", \n";
	                } else if (field.getType() == Date.class) {
	                    fildStr += "  " + fieldName + " datetime NOT NULL COMMENT " + fieldDesc + ",\n";
	                }
	            }
	        }
	
	        String sql = "CREATE TABLE " + tableName + " (\n" +
	                fildStr +
	                "  PRIMARY KEY (" + StringUtils.listToString(keyList1, ',') + ")\n" +
	                ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;";
	        System.out.print(sql);
	        System.out.print("\n");
        
	        String space = "\t\t\t\t";
	        String selectParams = "";
	        String callString = "";
	        String buildObject = space + className + " " + toLowerCaseFirstOne(className) + " = new " + className + "();";
	        buildObject += "\n";
	        for (Field field : fields) {
	            if (field.isAnnotationPresent(FieldTypeAnnotation.class)) {
	            	String fieldName = field.getName();
	            	FieldTypeAnnotation fieldTypeAnnotation = field.getAnnotation(FieldTypeAnnotation.class);
	                if (fieldTypeAnnotation.select()) {
	                    selectParams += field.getType().getSimpleName() + " " + fieldName + ",";
	                    callString += "call.set";
	                    if (field.getType() == String.class) {
	                        callString += "String";
	                    } else if (field.getType() == int.class) {
	                        callString += "Int";
	                    } else if (field.getType() == long.class) {
	                        callString += "Long";
	                    }
	                    callString += "(i++, " + fieldName + ");\n";
	                }
	                
	                String header = toLowerCaseFirstOne(className) + ".set" + toUpperCaseFirstOne(fieldName) + "(";
	                String tail = ");\n";
	                String sqlGetMethodName = "";
	                if (field.getType() == int.class) {
	                    sqlGetMethodName = "rs.getInt(\"" + fieldName + "\")";
	                } else if (field.getType() == long.class) {
	                    sqlGetMethodName = "rs.getLong(\"" + fieldName + "\")";
	                } else if (field.getType() == short.class) {
	                    sqlGetMethodName = "rs.getShort(\"" + fieldName + "\")";
	                } else if (field.getType() == boolean.class) {
	                    sqlGetMethodName = "rs.getBoolean(\"" + fieldName + "\")";
	                } else if (field.getType() == String.class || field.getType() == List.class) {
	                    sqlGetMethodName = "rs.getString(\"" + fieldName + "\")";
	                } else if (field.getType() == Date.class) {
	                    sqlGetMethodName = "rs.getTimestamp(\"" + fieldName + "\")";
	                } else if (field.getType() == BigInteger.class) {
	                    sqlGetMethodName = "new BigInteger(rs.getString(\"" + fieldName + "\"))";
	                } else if (field.getType() == Property.class) {
	                    sqlGetMethodName = "PropertyUtils.parseStringToProperty(rs.getString(\"" + fieldName + "\"))";
	                }
	                buildObject += space + header + sqlGetMethodName + tail;
	            }
	        }
	
	        buildObject += space + "list.add(" + toLowerCaseFirstOne(className) + ");\n";
	        if (!selectParams.isEmpty()) {
	        	selectParams = selectParams.substring(0, selectParams.length() - 1);
	        }
	
	        if (!tableName.isEmpty()) {
		        String selectSql = "select * from " + tableName + getWhereCondition(selectList);
		        selectSql += getOrderby(orderASCList, orderDESCList);
		        String baseVarName = className + "Sql";
		        String selectVarName = "get" + baseVarName;
		        System.out.println("\n\t// ========================================================================");
		        System.out.println("	private static String " + selectVarName + " = \"" + selectSql + "\";");
		        System.out.println("	public List<" + className + "> get" + className + "List(" + selectParams + ") {\n" +
		        		"		List<" + className + "> list = new ArrayList<>();\n" + 
		                "		ResultSet rs = null;\n" +
		                "		CallableStatement call = null;\n" +
		                "		try {\n" +
		                "			getDb().setConnName(DbNameStrategy.getServerDb());\n" +
		                "			call = getDb().getConnection().prepareCall("+ selectVarName + ");\n" +
		                "			int i = 1;\n" + 
		                "			" + callString + 
		                "			rs = call.executeQuery();\n" +
		                "			while (rs.next()) {\n" + buildObject +
		                "			}\n" +
		                "		} catch (Exception e) {\n" +
		                "			logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + \":\", e);\n" +
		                "		} finally {\n" +
		                "			getDb().closeConnection(call, rs);\n" +
		                "		}\n" +
		                "		return list;\n" +
		                "	}\n");
	        }
        }
        
        // 打印GET/SET=======================================================================
        String s = "";
        String ss = "";
        String varName = clz.getSimpleName().substring(0, 1).toLowerCase() + clz.getSimpleName().substring(1);
        for (Field field : fields) {
            // 判断是否被标记
        	String simpleName = field.getType().getSimpleName();
            String fieldName = field.getName();
            String fieldNamePart1 = fieldName.substring(0, 1).toUpperCase();
            String fieldNamePart2 = fieldName.substring(1);
            String firstUpperName = fieldNamePart1 + fieldNamePart2;

            if (field.isAnnotationPresent(FieldTypeAnnotation.class)) {
        		s += "	public " + simpleName + " get" + firstUpperName + "() {\n" +
                      "		return " + fieldName + ";\n" +
                      "	}\n";
        		s += "	public void set" + firstUpperName + "(" + simpleName + " " + fieldName + ") {\n" +
                      "			this." + fieldName + " = " + fieldName + ";\n" +
                      "	}\n\n";
        		ss += varName + ".set" + firstUpperName + "();\n";
            }
        }
        System.out.println("\n\t// ========================================================================");
        System.out.println(s);
        
        System.out.println("\n\t// ========================================================================");
        String sNew = clz.getSimpleName() + " " + varName + " = new " + clz.getSimpleName() + "();\n";
        sNew += ss;
        sNew += varName + ".setInsertOption();";
        System.out.println(sNew);
        System.out.println("\n\t// ========================================================================");
    }

    public static String getWhereCondition(List<String> list) {
        String sql = "";
        if (list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                if (i == 0) {
                    sql += " where ";
                }
                sql += list.get(i) + "=?";
                if (i + 1 < list.size()) {
                    sql += " and ";
                }
            }
        }
        return sql;
    }
    
    public static String getOrderby(List<String> orderASCList, List<String> orderDESCList) {
    	String orderby = "";
    	if (orderASCList.isEmpty() && orderDESCList.isEmpty()) {
    		return orderby;
    	}
    	if (!orderASCList.isEmpty() || !orderDESCList.isEmpty()) {
    		orderby += " ORDER BY ";
    	}
    	if (!orderASCList.isEmpty()) {
    		for (String str : orderASCList) {
    			orderby += str + ",";
    		}
    		orderby = orderby.substring(0, orderby.length() - 1);
    		orderby += " ASC,";
    	}
    	if (!orderDESCList.isEmpty()) {
    		for (String str : orderDESCList) {
    			orderby += str + ",";
    		}
    		orderby = orderby.substring(0, orderby.length() - 1);
    		orderby += " DESC,";
    	}
    	if (orderby.length() > 1) {
    		orderby = orderby.substring(0, orderby.length() - 1);
    	}
    	return orderby;
    }

    //首字母转小写
    public static String toLowerCaseFirstOne(String s){
        if(Character.isLowerCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
    }


    //首字母转大写
    public static String toUpperCaseFirstOne(String s){
        if(Character.isUpperCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
    }
}
